#include <stdio.h>
#include <time.h>
#include <curses.h>      //编译时加上-lncurses
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
 
#define BIRD '@'           //小鸟
#define BLANK ' '         //空白显示
#define PIPE '+'         //管道
 
 
int x, y;    //定义小鸟坐标
 
typedef struct Pipe {    //定义管道信息
	int x;
	int y;
	struct Pipe *next;
}Pipe_node, *Pipe_list;
 
Pipe_list head, tail;   //定义链表的头尾节点 
 
/*初始化相关工作*/
void Init_Curses();       //初始化ncurses库
int set_timer(int ms);    //set timer
void Catch_Signal();      //捕捉信号函数
 
/*小鸟*/
void Bird_Show();
void Bird_Clear();
void Bird_move();
 
/*管道*/
void Pipe_Create();     //list create
void Pipe_Show();       //显示管道
void Pipe_Clear();      //管道清楚
void Pipe_Move();       //管道移动
 
int main()
{
 
	y = 10, x = 15;          //小鸟的初始位置
 
	srand(time(0));          //给一个随机种子 
	Init_Curses();
	Catch_Signal();
	set_timer(500);
 
	Pipe_Create();
	Pipe_Show();
 
	Bird_Show();
	Bird_move();
 
 
	return 0;
}
 
/*初始化ncurses库*/
void Init_Curses() {
	initscr();   //进入ncurses模式
	curs_set(0); //禁止光标显示
	keypad(stdscr, 1);   //允许使用功能按键
	start_color();    //启用颜色机制
	noecho();    //禁止输入的字符显示
	init_pair(1, COLOR_WHITE, COLOR_RED);    //初始化颜色对
	init_pair(2, COLOR_WHITE, COLOR_GREEN);
}
 
/*设置定时器时间*/
int set_timer(int ms) {
	struct itimerval timer;
	long t_sec, t_usec;
	int ret;
	t_sec = ms / 1000;           // s
	t_usec = (ms % 1000) * 1000; // us
 
	timer.it_value.tv_sec= t_sec;     //第一次启动的时间
	timer.it_value.tv_usec = t_usec;
	timer.it_interval.tv_sec = t_sec;   //之后每隔多少时间启动一次
	timer.it_interval.tv_usec = t_usec;
 
	ret = setitimer(ITIMER_REAL, &timer, NULL);  //setitimer函数启动定时
 
	return ret;
}
 
/*信号是一种软中断*/
void handler(int sig) {
 
	int i, j;
	Pipe_list p, new1;
 
	Bird_Clear();
	y++;
	Bird_Show();
	if((char)inch() == PIPE) {
		set_timer(0);
		endwin();
		
		printf("Game over.\n");
		exit(0);
	}
 
	p = head->next;
	if(p->x == 0) {
		head->next = p->next;
		for(i = p->x; i < p->x + 10; i++) {
			for(j = 0; j < p->y; j++) {
				move(j, i);
				addch(BLANK);
			}	
 
			for(j = p->y + 5; j < 25; j++) {
				move(j, i);
				addch(BLANK);
			}	
			refresh();
		}
 
		free(p);
 
		new1 = (Pipe_list)malloc(sizeof(Pipe_node));
		new1->x = tail->x + 20;
		new1->y = rand() % 11 + 5;
		new1->next = NULL;
		tail->next = new1;
		tail = new1;
	}
 
	Pipe_Clear();
	Pipe_Move();
	Pipe_Show();
}
 
void Catch_Signal() {
	struct sigaction sig;
	sig.sa_handler = handler;
	sig.sa_flags = 0;
	sigemptyset(&sig.sa_mask);
 
	sigaction(SIGALRM, &sig, NULL);     //调用sigaction函数捕捉信号SIGALRM
/*
	struct sigaction {
		void     (*sa_handler)(int);
		void     (*sa_sigaction)(int, siginfo_t *, void *);
		sigset_t   sa_mask;
		int        sa_flags;
		void     (*sa_restorer)(void);
	};
*/
}
 
/*小鸟显示*/
void Bird_Show() {
	attron(COLOR_PAIR(1));
	move(y, x);
	addch(BIRD);
	refresh();
	attroff(COLOR_PAIR(1));
}
/*小鸟清除*/
void Bird_Clear() {
	move(y, x);
	addch(BLANK);
	refresh();
}
/*小鸟移动*/
void Bird_move() {
	char key;
	while(1) {
		key = getch();
		if(key == ' ') {
			Bird_Clear();
			y--;
			Bird_Show();
			if((char)inch() == PIPE) {    //游戏结束标志判断
				set_timer(0);
				endwin();
				printf("Game over.\n");
				exit(0);
			}
		}
		/*
		if(key = 'q') {
			set_timer(0);
			endwin();
			printf("Quit!\n");
			exit(0);
		}
		*/
	}
}
/*链表的创建*/
void Pipe_Create() {
	Pipe_list p, q;
	int i;
	p = (Pipe_list)malloc(sizeof(Pipe_node));
	p->next = NULL;
 
	
	head = p;
	for(i = 0; i < 5; i++) {
		q = (Pipe_list)malloc(sizeof(Pipe_node));
		q->x = (i + 1)  * 20;     //列宽为20
		q->y = rand() % 11 + 5;   //行的值为随机值，　增加可玩性
		q->next = NULL;
		p->next = q;
		p = p->next;
	}
	tail = p; 
 
}
 
/*管道的显示*/
void Pipe_Show() {
	Pipe_list p;
	int i, j;
 
	p = head->next;
	attron(COLOR_PAIR(2));
	while(p != NULL) {
		for(i = p->x; i < p->x + 10; i++) {
			for(j = 0; j < p->y; j++) {
				move(j, i);
				addch(PIPE);
			}	
 
			for(j = p->y + 5; j < 25; j++) {
				move(j, i);
				addch(PIPE);
			}	
		}
 
		refresh();
		p = p->next;   //移动到下一个节点，　准备显示下一个管道
	}
	attroff(COLOR_PAIR(2));
	
}
 
/*管道的清除*/
void Pipe_Clear() {
	Pipe_list p;
	int i, j;
 
	p = head->next;
	while(p != NULL) {
		for(i = p->x; i < p->x + 10; i++) {
			for(j = 0; j < p->y; j++) {
				move(j, i);
				addch(BLANK);
			}	
 
			for(j = p->y + 5; j < 25; j++) {
				move(j, i);
				addch(BLANK);
			}	
		}
 
		refresh();
		p = p->next;
	}
}
 
/*管道的移动*/
void Pipe_Move() {
	Pipe_list p;
 
	p = head->next;
	while(p != NULL) {
		p->x--;
		p = p->next;
	}
	
}
                        
